home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / todir1.arc / TODIR.ASM < prev    next >
Assembly Source File  |  1990-08-14  |  29KB  |  1,043 lines

  1.  
  2.     title    TODIR - Change dir through alias
  3.     subttl    Prologue
  4.     page    60, 132
  5.  
  6. comment {
  7.  
  8. ******************************************************************************
  9.  
  10. File TODIR.ASM
  11.  
  12. Author:
  13.     Aaron Brenner
  14.  
  15.     GEnie mail address A.BRENNER
  16.     BIX user id albrenner
  17.  
  18.     This program is hereby released to the public domain.
  19.  
  20. Purpose:
  21.     Provide a shorthand for CHDIR. TODIR will read the file TODIR.PTH in
  22.     either the current directory, on the PATH, or in the directory speci-
  23.     fied by the TODIRPTH environment variable. TODIR.PTH must be an ASCII
  24.     file containing shorthand/path pairs, one per line, blank separated.
  25.  
  26.     Alias are limited to 12 characters in length, and may contain any
  27.     printable characters.
  28.  
  29. Syntax:
  30.     C>TODIR
  31.     Displays a usage message.
  32.  
  33.     C>TODIR
  34.     Displays all alias/path pairs.
  35.  
  36.     C>TODIR <path alias>
  37.     Changes the current directory (and current drive, if necessary) to the
  38.     path corresponding to <path alias>.
  39.  
  40. Errorlevel set:
  41.     0    Path set successfully.
  42.     1    Unable to locate TODIR.PTH.
  43.     2    Unable to locate alias in TODIR.PTH.
  44.     3    No path associated with alias.
  45.     4    Unable to change drive/directory to path.
  46.     5    No command argument present.
  47.     6    Not enough memory
  48.  
  49. Revision history:
  50. 1.00    07/15/90    ALB    Created.
  51.  
  52. ******************************************************************************
  53.  
  54. endcomment {
  55.  
  56.  
  57.     subttl    Macros
  58.     page
  59.  
  60. save    macro    p1,p2,p3,p4,p5,p6,p7,p8,p9
  61.     irp    y,<p1,p2,p3,p4,p5,p6,p7,p8,p9>
  62.     ifnb    <y>
  63.     push    y
  64.     endif
  65.     endm
  66. restore macro
  67.     irp    z,<p9,p8,p7,p6,p5,p4,p3,p2,p1>
  68.     ifnb    <z>
  69.     pop    z
  70.     endif
  71.     endm
  72.     endm
  73.     endm
  74.  
  75.  
  76.     subttl    Program stack and data
  77.     page
  78.  
  79. todir_stack    segment    stack
  80.  
  81.     dw    128 dup(0)
  82.  
  83. todir_stack    ends
  84.  
  85.  
  86. todir_data    segment
  87.  
  88. $buf_size    equ    4096
  89.  
  90. our_env_seg    dw    0        ; Pointer to our environment segment
  91. our_PSP        dw    0        ; Our PSP segment
  92. buffer_posn    dw    $buf_size    ; Current position in the buffer
  93. buffer_seg    dw    0        ; Segment of the file buffer
  94. buffer_count    dw    0        ; Count of characters in the buffer
  95. saved_char    dw    -1        ; An ungotten character
  96. line_buf    db    128 dup (0)    ; Buffer for a line
  97.  
  98. ;*****************************************************************************
  99. ;
  100. ; Error messages
  101. ;
  102. ; Note that the routine that does the output will interpret the following
  103. ; control characters:
  104. ;    ^A    output the alias entered on the command line
  105. ;    ^B    output the path associated with the alias
  106. ;
  107. ;*****************************************************************************
  108. usage_msg    db    'TODIR v1.00 - Public Domain Software', 13, 10, 13, 10
  109.         db    'Usage: TODIR <path alias>', 13, 10
  110.         db    ' or    TODIR ?', 13, 10
  111.         db    ' or    TODIR <path alias> ?', 13, 10, 13, 10
  112.         db    'Change drive/directory to the path corresponding to'
  113.         db    ' <path alias> as set', 13, 10
  114.         db    'in TODIR.PTH.', 13, 10
  115.         db    'An argument of ? will display all alias/path pairs in'
  116.         db    ' TODIR.PTH.', 13, 10
  117.         db    'A <path alias> followed by ? will display the path'
  118.         db    ' associated with that alias.', 13, 10, '$'
  119.  
  120. all_aliases    db    'All aliases in ', 3, ':', 13, 10, 0
  121. no_alias_path    db    'No path associated with "', 1, '".', 13, 10, 0
  122. no_alias_fnd    db    'Alias "', 1, '" not found.', 13, 10, 0
  123. bad_path    db    'Unable to change to "', 2, '".', 13, 10, 0
  124. no_pth_file    db    'Unable to locate alias definition file.', 13, 10, '$'
  125. no_memory    db    'Not enough free memory', 13, 10, '$'
  126. crlf_string    db    13, 10
  127.  
  128. command_tail    db    127 dup (0)    ; Copy of our command tail
  129.  
  130. alias_name    db    14 dup (0)    ; The alias they entered
  131. alias_path    db    80 dup (0)    ; The path associated with it
  132. possible_alias    db    14 dup (0)    ; A possible one from the file
  133. path_file_name    db    80 dup (0)    ; Where we found TODIR.PTH
  134. path_file_hnd    dw    -1        ; Handle for it
  135. path_name_base    db    'TODIR.PTH',0    ; Base name of path file
  136. $name_base_len    =    $ - path_name_base
  137.  
  138. ;
  139. ; Environment variables to look for
  140. ;
  141. env_path    db    'PATH='
  142. $env_path_len    =    $ - env_path
  143. env_todir    db    'TODIRPTH='
  144. $env_todir_len    =    $ - env_todir
  145.  
  146. env_buffer    db    256 dup (0)    ; Buffer to hold the env contents
  147.  
  148. todir_data    ends
  149.  
  150.  
  151.     subttl    Program code
  152.     page
  153.  
  154. todir_code    segment
  155.  
  156. assume    cs:todir_code, ds:nothing, es:nothing, ss:todir_stack
  157.  
  158.  
  159. start    proc
  160.  
  161.     call    initialize        ; Set everything up
  162.     call    change_path        ; Change to where they want
  163.     mov    ax,4c00h        ; Exit to DOS with ERRORLEVEL 0
  164.     int    21h            ;
  165.  
  166. start    endp
  167.  
  168.     subttl    Program initialization
  169.     page
  170.  
  171. ;*****************************************************************************
  172. ;
  173. ; Program initialization
  174. ;
  175. ;*****************************************************************************
  176. initialize    proc    near
  177.  
  178.     mov    ax,todir_data        ; Set up our data segment
  179.     mov    es,ax            ;
  180.  
  181. assume    es:todir_data
  182.  
  183.     mov    es:our_PSP,ds        ; Save our PSP segment
  184.     mov    ax,ds:[2ch]        ; Get our environment segment
  185.     mov    es:our_env_seg,ax    ; Save it
  186.     mov    di,offset command_tail    ; Point to our buffer for the cmd tail
  187.     mov    si,81h            ; Point to our command tail
  188.     mov    cl,ds:[80h]        ; Get the length of the command tail
  189.     sub    ch,ch            ;  as a word
  190.     cld                ; Make sure of direction
  191.     rep    movsb            ; Copy the command tail
  192.     sub    al,al            ; Null-terminate it
  193.     stosb                ;
  194.     push    es            ; Set our data segment now
  195.     pop    ds            ;
  196.  
  197. assume    ds:todir_data
  198.  
  199.     mov    si,offset command_tail    ; Point to our copy of the cmd tail
  200.     mov    di,offset alias_name    ; Point to alias name buffer
  201.     mov    cx,12            ; Max to copy
  202.     call    copy_string        ; Copy it
  203.     cmp    byte ptr alias_name[0],0; Did they enter one?
  204.     jne    init_l2            ; Yep - check for "?"
  205. ;
  206. ; No command line arg. Just display the usage message and exit 5.
  207. ;
  208.     mov    dx,offset usage_msg    ; Point to the usage message
  209.     mov    ah,9            ; Display it to console
  210.     int    21h            ; Display the usage message
  211.     mov    ax,4c05h        ; Exit with ERRORLEVEL of 5
  212.     int    21h            ;
  213. init_l2:
  214.     mov    bx,offset program_end + 15; Figure out where we end
  215.     mov    cl,4            ;
  216.     shr    bx,cl            ;
  217.     mov    ax,cs            ;
  218.     add    bx,ax            ;
  219.     sub    bx,our_PSP        ; Figure out our size
  220.     push    es            ; Save this for a sec
  221.     mov    es,our_PSP        ;  for the SETBLOCK call
  222.     mov    ah,4ah            ; Set our allocation
  223.     int    21h            ;
  224.     pop    es            ;
  225.     mov    ah,48h            ; Now, allocate a file buffer
  226.     mov    bx,$buf_size shr 4    ; Number of paragraphs for the buffer
  227.     int    21h            ;
  228.     jnc    init_l3            ; We got it - continue
  229.     mov    dx,offset no_memory    ; Report there ain't enough RAM
  230.     mov    ah,9            ;
  231.     int    21h            ;
  232.     mov    ax,4c06h        ; Exit with appropriate ERRORLEVEL
  233.     int    21h            ;
  234. init_l3:
  235.     mov    buffer_seg,ax        ; Save the returned segment
  236.     call    locate_file        ; Get the file
  237.     cmp    word ptr alias_name[0],('?' * 256) + 1; Was it just "?"?
  238.     jne    init_l4            ; No - see if more args
  239. ;
  240. ; The first command line arg was a "?". We just want to display the entire
  241. ; list of alias/path pairs.
  242. ;
  243.     call    display_file        ; Display the .PTH file
  244.     mov    ax,4c00h        ; Pretend we did the change
  245.     int    21h            ;
  246. ;
  247. init_l4:
  248.     call    skip_spaces        ; Skip any more whitespace
  249.     lodsb                ; Get the next byte
  250.     or    al,al            ; End of the command line?
  251.     je    init_exit        ; Yep - finish up here
  252.     cmp    al,'?'            ; Are they querying?
  253.     jne    init_exit        ; No - just finish up
  254.     call    match_alias        ; Match the alias they entered
  255.     call    display_pair        ; Display the alias/path pair
  256.     mov    ax,4c00h        ; Pretend we did the change
  257.     int    21h            ;
  258. ;
  259. init_exit:
  260.     call    match_alias        ; Find a match for the alias
  261.     ret                ; Return to Main
  262.  
  263. initialize    endp
  264.  
  265.  
  266. ;*****************************************************************************
  267. ;
  268. ; Attempt to change the drive/path to that in alias_path.
  269. ;
  270. ;*****************************************************************************
  271. change_path    proc    near
  272.  
  273. assume    ds:todir_data, es:todir_data
  274.  
  275.     cmp    byte ptr alias_path[0],0; Is there a path there?
  276.     jne    chgp_l1            ; Yes - try to change to it
  277.     mov    si,offset no_alias_path    ; Point to error message
  278.     call    display_message        ; Spit it out
  279.     mov    ax,4c03h        ; Exit with ERRORLEVEL 3
  280.     int    21h            ;
  281. ;
  282. chgp_l1:
  283.     mov    dx,offset alias_path[1]    ; Point to the path to switch to
  284.     mov    ah,3bh            ; DOS fn to change current dir
  285.     int    21h            ; Try to do it
  286.     jnc    chgp_l2            ; It flew - continue
  287.     mov    si,offset bad_path    ; Point to error message
  288.     call    display_message        ; Show it
  289.     mov    ax,4c04h        ; Exit with appropriate ERRORLEVEL
  290.     int    21h            ;
  291. ;
  292. chgp_l2:
  293.     mov    ax,word ptr alias_path[1]; Get the first 2 bytes of the string
  294.     cmp    ah,':'            ; Is there a drive present?
  295.     jne    chgp_exit        ; Nope - we're done
  296.     sub    al,'A'            ; Make it a disk number
  297.     mov    dl,al            ; Put it where DOS wants
  298.     mov    ah,0eh            ; Fn to select drive
  299.     int    21h            ;
  300. chgp_exit:
  301.     ret                ; Return to Main
  302.  
  303. change_path    endp
  304.  
  305.  
  306.     subttl    Various utility routines
  307.     page
  308.  
  309. ;*****************************************************************************
  310. ;
  311. ; U t i l i t y   R o u t i n e s
  312. ;
  313. ;*****************************************************************************
  314.  
  315.  
  316. ;*****************************************************************************
  317. ;
  318. ; Locate the file TODIR.PTH. The search order is:
  319. ;    1. In the path specified by the TODIRPTH environment variable. If this
  320. ;       specifies a directory, the file name is assumed to be TODIR.PTH.
  321. ;    2. In a directory specified by the PATH environment variable.
  322. ;    3. In the current directory.
  323. ;
  324. ; Input:
  325. ;    None.
  326. ;
  327. ; Output:
  328. ;    path_file_name is filled in with the file spec, and the handle for
  329. ;    the file is stored in path_file_handle
  330. ;
  331. ; Registers:
  332. ;    All preserved.
  333. ;
  334. ;*****************************************************************************
  335. locate_file    proc    near
  336.  
  337. assume    ds:todir_data, es:todir_data
  338.  
  339.     save    ax, bx, cx, dx, si, di
  340.     mov    si,offset env_todir    ; Point to the "TODIRPTH" var name
  341.     mov    cx,$env_todir_len    ; Get the length of it
  342.     call    getenv            ; Try to get it
  343.     cmp    byte ptr env_buffer[0],0; Is there a path there?
  344.     je    lctf_on_path        ; Nope - look along the path
  345.     mov    si,offset env_buffer    ; Copy it into our path
  346.     mov    di,offset path_file_name;
  347.     mov    cx,78            ;
  348.     call    copy_string        ;
  349.     cmp    byte ptr [di - 1],'\'    ; Is there a path sep?
  350.     je    lctf_l1            ; Yep - just tack on the file name
  351.     cmp    byte ptr [di - 1],'/'    ; Check for other path sep
  352.     je    lctf_l1            ; Yep - tack on the file name
  353.     mov    dx,offset path_file_name[1];
  354.     mov    ax,4300h        ; See if it's a file or a dir
  355.     int    21h            ;
  356.     jc    lctf_on_path        ; If unable, look along the path
  357.     test    cx,10h            ; Is this a directory?
  358.     jz    lctf_l2            ; Nope - use that file name
  359.     mov    al,'\'            ; Put in a path separator
  360.     stosb                ;
  361.     inc    path_file_name        ; Account for it
  362. lctf_l1:
  363.     mov    si,offset path_name_base; Point to the file name
  364.     mov    cx,$name_base_len    ; Size of it
  365.     rep    movsb            ; Copy to the path (terminates it, too)
  366.     add    path_file_name,$name_base_len - 1; Add to string length
  367. lctf_l2:
  368.     mov    dx,offset path_file_name[1]; Get ready to open it
  369.     mov    ax,3d00h        ; Open for read-only
  370.     int    21h            ; Try to open that puppy
  371.     jnc    lctf_done        ; If we did, save the handle & exit
  372. lctf_on_path:
  373.     mov    si,offset env_path    ; Point to "PATH="
  374.     mov    cx,$env_path_len    ; Get the length of it
  375.     call    getenv            ; Get the value for it
  376.     cmp    env_buffer[0],0        ; Is there a PATH defined?
  377.     je    lctf_curr_dir        ; Nope - try current directory
  378. ;
  379. ; To make things a little easier to deal with, step through the PATH string,
  380. ; replacing ";" with " ".
  381. ;
  382.     mov    si,offset env_buffer    ; Point to the PATH string
  383.     mov    di,si            ; Twice
  384. lctf_l3:
  385.     lodsb                ; Get a character
  386.     cmp    al,';'            ; Is it one we need to change?
  387.     jne    lctf_l4            ; No - store it
  388.     mov    al,' '            ; Replace it with a blank
  389. lctf_l4:
  390.     stosb                ; Stuff it back in
  391.     or    al,al            ; Hit the end yet?
  392.     jnz    lctf_l3            ; Nope - check the whole thing
  393.     mov    si,offset env_buffer    ; Start back at the beginning
  394. lctf_l5:
  395.     mov    di,offset path_file_name; Point to the final path name
  396.     mov    cx,65            ; Biggest path allowed by DOS
  397.     call    copy_string        ; Copy it in
  398.     cmp    path_file_name[0],0    ; Is there anything there?
  399.     je    lctf_curr_dir        ; No - look in the current directory
  400.     cmp    byte ptr [di - 1],'\'    ; Is there a path sep?
  401.     je    lctf_l6            ; Yes - just add the file name
  402.     cmp    byte ptr [di - 1],'/'    ; Other path sep?
  403.     je    lctf_l6            ; Yep - continue
  404.     mov    al,'\'            ; Add a path separator
  405.     stosb                ;
  406.     inc    path_file_name        ; Account for it in the length
  407. lctf_l6:
  408.     push    si            ; Save where we were
  409.     mov    si,offset path_name_base; Point to the actual file name
  410.     mov    cx,$name_base_len    ; Size of it
  411.     rep    movsb            ; Copy it into the final file spec
  412.     pop    si            ;
  413.     add    path_file_name[0],$name_base_len - 1; Account for it
  414.     mov    dx,offset path_file_name[1]; Try to open that baby
  415.     mov    ax,3d00h        ;
  416.     int    21h            ;
  417.     jnc    lctf_done        ; If it went, save the handle & exit
  418.     jmp    short lctf_l5        ; Not there - try next path
  419. lctf_curr_dir:
  420. ;
  421. ; The file isn't on the path and it isn't in the TODIRPTH path. Try the
  422. ; current directory. If it isn't there, report an error.
  423. ;
  424.     mov    dx,offset path_name_base; Point to base file name
  425.     mov    ax,3d00h        ; Try to open it
  426.     int    21h            ;
  427.     jnc    lctf_done        ; No error - save the handle and exit
  428.     mov    dx,offset no_pth_file    ; Let 'em know we couldn't find it
  429.     mov    ah,9            ;
  430.     int    21h            ;
  431.     mov    ax,4c01h        ; Exit w/ERRORLEVEL of 1
  432.     int    21h            ;
  433. ;
  434. lctf_done:
  435.     mov    path_file_hnd,ax    ; Save the handle
  436.     restore
  437.     ret                ; Return to caller
  438.  
  439. locate_file    endp
  440.  
  441.  
  442. ;*****************************************************************************
  443. ;
  444. ; Retrieve the contents of an environment variable.
  445. ;
  446. ; Input:
  447. ;    DS:SI        pointer to the name (including the "=") of the var
  448. ;    CX        length of the name (including the "=")
  449. ;
  450. ; Output:
  451. ;    env_buffer will be filled with the contents of the variable. If the
  452. ;    first byte of env_buffer is 0, then the variable wasn't found. Up to
  453. ;    255 characters will be copied.
  454. ;
  455. ; Registers:
  456. ;    All preserved.
  457. ;
  458. ;*****************************************************************************
  459. getenv        proc    near
  460.  
  461. assume    ds:todir_data, es:todir_data
  462.  
  463.     save    ax, bx, cx, dx, di, ds
  464.     mov    es,our_env_seg        ; Get our environment segment
  465.  
  466. assume    es:nothing
  467.  
  468.     sub    ax,ax            ; We'll be scanning for a 0 byte
  469.     sub    di,di            ; Start at the beginning of it
  470.     mov    bx,si            ; Save the pointer to the name
  471.     mov    dx,cx            ; Save its length
  472. gtnv_l1:
  473.     repe    cmpsb            ; See if we've found it
  474.     je    gtnv_l2            ; Yep - copy the contents
  475.     mov    cx,-1            ; Look forever for the end of this one
  476.     repne    scasb            ; Find the end of this var
  477.     mov    si,bx            ; Restore the pointer & length
  478.     mov    cx,dx            ;
  479.     cmp    byte ptr es:[di],0    ; End of the environment?
  480.     jne    gtnv_l1            ; No - keep looking
  481. gtnv_l2:
  482.     mov    si,di            ; Get ready to copy from the environment
  483.     push    ds            ; Swap segments
  484.     push    es            ;
  485.     pop    ds            ;
  486.     pop    es            ;
  487.  
  488. assume    ds:nothing, es:todir_data
  489.  
  490.     mov    di,offset env_buffer    ; Point to the destination
  491.     mov    cx,255            ; Max to copy
  492. gtnv_l3:
  493.     lodsb                ; Copy a byte
  494.     stosb                ;
  495.     or    al,al            ; Did we just copy the ender?
  496.     loopnz    gtnv_l3            ; Loop if not
  497.     restore
  498.  
  499. assume    ds:todir_data
  500.  
  501.     ret                ; Return to caller
  502.  
  503. getenv        endp
  504.  
  505.  
  506. ;*****************************************************************************
  507. ;
  508. ; Display an alias/path pair
  509. ;
  510. ; Input:
  511. ;    possible_alias    set to the alias to display
  512. ;    alias_path    set to the corresponding path
  513. ;
  514. ; Output:
  515. ;    Both are displayed.
  516. ;
  517. ; Registers:
  518. ;    All preserved.
  519. ;
  520. ;*****************************************************************************
  521. display_pair    proc    near
  522.  
  523.     save    ax, bx, cx, dx, si
  524.     mov    si,offset possible_alias; Display the alias name first
  525.     mov    al,[si]            ; Get the length
  526.     cbw                ;  as a word
  527.     call    display_string        ; Display the alias
  528.     mov    cx,16            ; Use field width of 16
  529.     sub    cx,ax            ; Figure out how many blanks to output
  530.     mov    dl,' '            ;
  531. dspp_l1:
  532.     mov    ah,6            ; Output a space
  533.     int    21h            ;
  534.     loop    dspp_l1            ; Loop to fill out field
  535.     mov    si,offset alias_path    ; Now, display the associated path
  536.     call    display_string        ;
  537.     mov    dx,offset crlf_string    ; End this line
  538.     mov    cx,2            ;
  539.     mov    bx,1            ;
  540.     mov    ah,40h            ;
  541.     int    21h            ;
  542.     restore
  543.     ret                ; Return to caller
  544.  
  545. display_pair    endp
  546.  
  547.  
  548. ;*****************************************************************************
  549. ;
  550. ; Display the entire alias file
  551. ;
  552. ; Input:
  553. ;    path_file_hnd    handle to read from
  554. ;
  555. ; Output:
  556. ;    The file is displayed as a series of alias/path pairs.
  557. ;
  558. ; Registers:
  559. ;    All preserved.
  560. ;
  561. ;*****************************************************************************
  562. display_file    proc    near
  563.  
  564.     save    si
  565.     mov    si,offset all_aliases    ; Display the name of the file
  566.     call    display_message        ;
  567. dspf_l1:
  568.     call    get_pair        ; Get a pair from the file
  569.     jc    dspf_exit        ; If EOF, we're done
  570.     call    display_pair        ; Display that pair
  571.     jmp    short dspf_l1        ; Loop back 'til EOF
  572. dspf_exit:
  573.     restore
  574.     ret                ; Return to caller
  575.  
  576. display_file    endp
  577.  
  578.  
  579. ;*****************************************************************************
  580. ;
  581. ; Read an alias/path pair from the file
  582. ;
  583. ; Input:
  584. ;    None.
  585. ;
  586. ; Output:
  587. ;    CF    = 1    EOF has been reached (^Z is recognized as EOF)
  588. ;    CF    = 0:
  589. ;    possible_alias    the alias read from the file
  590. ;    alias_path    the corresponding path
  591. ;
  592. ; Registers:
  593. ;    All preserved
  594. ;
  595. ;*****************************************************************************
  596. get_pair    proc    near
  597.  
  598.     save    cx, si, di
  599. getp_l1:
  600.     call    get_line        ; Get a line from the file
  601.     jc    getp_exit        ; Exit if EOF
  602.     cmp    line_buf[0],0        ; Empty line?
  603.     je    getp_l1            ; Yep - ignore it
  604.     mov    si,offset line_buf    ; Point to the line buffer
  605.     mov    di,offset possible_alias; And to the name buffer
  606.     mov    cx,12            ; Max to copy
  607.     call    copy_string        ; Copy the alias name
  608.     cmp    possible_alias[0],0    ; Empty line?
  609.     je    getp_l1            ; Yep - ignore it
  610.     mov    di,offset alias_path    ; Point to the path buffer
  611.     mov    cx,65            ; Max to copy
  612.     call    copy_string        ; Copy to the aliased path
  613.     clc                ; Make sure we return success
  614. getp_exit:
  615.     restore
  616.     ret                ; Return to caller
  617.  
  618. get_pair    endp
  619.  
  620.  
  621. ;*****************************************************************************
  622. ;
  623. ; Get a line of text from the path file
  624. ;
  625. ; Input:
  626. ;    None.
  627. ;
  628. ; Output:
  629. ;    CF = 1        EOF has been reached.
  630. ;    CF = 0:
  631. ;    line_buf is set to the next line from the file. All alphas are
  632. ;    folded to upper case.
  633. ;
  634. ; Registers:
  635. ;    All preserved.
  636. ;
  637. ;*****************************************************************************
  638. get_line    proc    near
  639.  
  640. assume    ds:todir_data, es:todir_data
  641.  
  642.     save    ax, cx, di
  643.     mov    di,offset line_buf    ; Point to our line buffer
  644.     mov    cx,127            ; Max to store
  645. getl_l1:
  646.     call    get_char        ; Get a character from the file
  647.     jz    getl_EOF        ; Exit if EOF
  648.     cmp    al,13            ; Is it a CR?
  649.     je    getl_l2            ; Yep - check for LF following
  650.     cmp    al,10            ; Is it a LF?
  651.     je    getl_l3            ; Yep - check for CR following
  652.     jcxz    getl_l1            ; Ignore it if the buffer's full
  653.     call    casetize        ; Make it upper case
  654.     stosb                ; Stuff it in
  655.     dec    cx            ; Knock it off the count
  656.     jmp    short getl_l1        ; Loop back for more
  657. getl_l2:
  658.     call    get_char        ; Get the NEXT character
  659.     jz    getl_eof        ; Stop if EOF
  660.     cmp    al,10            ; Is it the LF following a CR?
  661.     je    getl_exit        ; Yep - we're done with this line
  662.     mov    ah,1            ;
  663.     mov    saved_char,ax        ; Save it for next time
  664.     jmp    short getl_exit1    ; Exit now
  665. getl_l3:
  666.     call    get_char        ; Get the NEXT character
  667.     jz    getl_eof        ; Stop if EOF
  668.     cmp    al,13            ; Is it the CR following a LF?
  669.     je    getl_exit        ; Yep - we're done with this line
  670.     mov    ah,1            ;
  671.     mov    saved_char,ax        ; Save it for next time
  672.     jmp    short getl_exit1    ; Exit now
  673. getl_EOF:
  674. ;
  675. ; We get here when get_char reports we've reached EOF. We only want to return
  676. ; EOF when the line's empty.
  677. ;
  678.     cmp    di,offset line_buf[1]    ; Are we at the beginning of the buf?
  679.     jmp    short getl_exit        ; If we are, CF will be 1
  680. getl_exit1:
  681.     clc                ; Make sure we don't report EOF
  682. getl_exit:
  683.     mov    byte ptr [di],0        ; Terminate the line buffer
  684.     restore
  685.     ret                ; Return to caller
  686.  
  687. get_line    endp
  688.  
  689.  
  690. ;*****************************************************************************
  691. ;
  692. ; Attempt to match the alias from the command line with one from the file.
  693. ;
  694. ; Input:
  695. ;    alias_name    set to the alias to look for
  696. ;
  697. ; Output:
  698. ;    alias_path    set to the corresponding path
  699. ;
  700. ; Registers:
  701. ;    All preserved.
  702. ;
  703. ;*****************************************************************************
  704. match_alias    proc    near
  705.  
  706.     save    cx, si, di
  707.     mov    ch,0            ; Make sure high byte is clear
  708. mtch_l1:
  709.     call    get_pair        ; Get an alias/path pair
  710.     jc    mtch_err        ; Oops - if EOF, no matches
  711.     mov    cl,alias_name[0]    ; Get length of our alias
  712.     inc    cl            ; Allow for length byte
  713.     mov    si,offset alias_name    ; Point to the one they entered
  714.     mov    di,offset possible_alias; Point to the one from the file
  715.     repe    cmpsb            ; See if they match
  716.     jnz    mtch_l1            ; Nope - keep trying
  717.     restore
  718.     ret                ; Return to caller
  719. ;
  720. mtch_err:
  721. ;
  722. ; We get here if we hit EOF - that means that there is no possible match for
  723. ; the given alias.
  724. ;
  725.     mov    si,offset no_alias_fnd    ; Let 'em know it ain't there
  726.     call    display_message        ;
  727.     mov    ax,4c02h        ; Exit with appropriate ERRORLEVEL
  728.     int    21h            ;
  729.  
  730. match_alias    endp
  731.  
  732.  
  733. ;*****************************************************************************
  734. ;
  735. ; Get the next character from the file.
  736. ;
  737. ; Input:
  738. ;    buffer_seg    segment of file data buffer
  739. ;    buffer_posn    current position the buffer
  740. ;    buffer_count    number of characters in the buffer
  741. ;
  742. ; Output:
  743. ;    ZF = 1        EOF has been reached
  744. ;    ZF = 0:
  745. ;    AL        next character.
  746. ;
  747. ; Registers:
  748. ;    All but AX preserved.
  749. ;
  750. ;*****************************************************************************
  751. get_char    proc    near
  752.  
  753. assume    ds:todir_data, es:todir_data
  754.  
  755.     save    si, es
  756.     sub    ax,ax            ; See if there was a saved character
  757.     dec    ax            ;
  758.     xchg    ax,saved_char        ;
  759.     cmp    ax,-1            ;
  760.     je    getc_l1            ; Nope - read the next one in
  761.     or    ax,ax            ; Make sure and clear ZF
  762.     jmp    short getc_exit        ; Exit now
  763. getc_l1:
  764.     cmp    buffer_count,0        ; Is the buffer empty?
  765.     jne    getc_l2            ; Nope - read the next byte from it
  766.     call    fill_buffer        ;
  767.     jz    getc_exit        ; EOF - return it
  768. getc_l2:
  769.     les    si,dword ptr buffer_posn; Point at the next available byte
  770.  
  771. assume    es:nothing
  772.  
  773.     lods    byte ptr es:[si]    ; Get it from the buffer
  774.     cmp    al,1ah            ; Is it the fake EOF?
  775.     je    getc_exit        ; Yep - exit with ZF set
  776.     dec    buffer_count        ; Knock it off the count
  777.     mov    buffer_posn,si        ; Save updated buffer position
  778.     or    si,si            ; Clear ZF for return
  779. getc_exit:
  780.     restore
  781.  
  782. assume    es:todir_data
  783.  
  784.     ret                ; Return to caller
  785.  
  786. get_char    endp
  787.  
  788.  
  789. ;*****************************************************************************
  790. ;
  791. ; Fill the buffer from the file.
  792. ;
  793. ; Input:
  794. ;    path_file_hnd    handle to read from
  795. ;
  796. ; Output:
  797. ;    ZF = 1        EOF has been reached
  798. ;    ZF = 0:
  799. ;    buffer_posn    set to beginning of buffer
  800. ;    buffer_count    set to the number of bytes actually read
  801. ;
  802. ; Registers:
  803. ;    All preserved.
  804. ;
  805. ;*****************************************************************************
  806. fill_buffer    proc    near
  807.  
  808. assume    ds:todir_data, es:todir_data
  809.  
  810.     save    ax, bx, cx, dx
  811.     mov    bx,path_file_hnd    ; Get the handle
  812.     mov    cx,$buf_size        ; Number of bytes to try to read
  813.     sub    dx,dx            ; Start at 0 in the buffer
  814.     push    ds            ; Save our seg for a sec
  815.     mov    ds,buffer_seg        ; Get the segment for the buffer
  816.     mov    ah,3fh            ; DOS fn to read
  817.     int    21h            ; Try to read from the file
  818.     pop    ds            ; Get our segment back
  819.     jnc    filb_l1            ; If no error, reset pointer & count
  820.     sub    ax,ax            ; Act like we hit EOF
  821. filb_l1:
  822.     mov    buffer_count,ax        ; Save how many we read
  823.     mov    buffer_posn,0        ; Reset to start of buffer
  824.     or    ax,ax            ; If we hit EOF, set ZF
  825. filb_exit:
  826.     restore
  827.     ret                ; Return to caller
  828.  
  829. fill_buffer    endp
  830.  
  831.  
  832. ;*****************************************************************************
  833. ;
  834. ; Skip spaces in a string.
  835. ;
  836. ; Input:
  837. ;    DS:SI        pointer to string
  838. ;
  839. ; Output:
  840. ;    DS:SI        pointer to first non-blank
  841. ;
  842. ; Registers:
  843. ;    All but SI preserved.
  844. ;
  845. ;*****************************************************************************
  846. skip_spaces    proc    near
  847.  
  848.     save    ax
  849. sksp_l1:
  850.     lodsb                ; Get a character
  851.     cmp    al,' '            ; Is it a space?
  852.     je    sksp_l1            ; Yep - skip it
  853.     cmp    al,9            ; Is it a tab?
  854.     je    sksp_l1            ; Yep - skip it
  855.     dec    si            ; Point back to it
  856.     restore
  857.     ret                ; Return to caller
  858.  
  859. skip_spaces    endp
  860.  
  861.  
  862. ;*****************************************************************************
  863. ;
  864. ; Copy a string, making it upper case.
  865. ;
  866. ; Input:
  867. ;    DS:SI        pointer to source buffer. May have leading whitespace,
  868. ;            and is assumed to be nul-terminated.
  869. ;    ES:DI        pointer to dest buffer.
  870. ;    CX        maximum characters to copy
  871. ;
  872. ; Output:
  873. ;    First byte of buffer at DI will be set to the length copied, and all
  874. ;    alphas are folded to upper case. SI will point to the character just
  875. ;    *after* the last character that was copied, and DI will point to a
  876. ;    nul byte at the end of the string.
  877. ;
  878. ; Registers:
  879. ;    All but SI and DI preserved.
  880. ;
  881. ;*****************************************************************************
  882. copy_string    proc    near
  883.  
  884. assume    ds:todir_data, es:todir_data
  885.  
  886.     save    ax, bx, cx
  887.     mov    byte ptr es:[di],0    ; Clear the dest length
  888.     call    skip_spaces        ; Skip any whitespace
  889.     mov    bx,di            ; Point to the length byte
  890.     inc    di            ; Point to the first available byte
  891. cpys_l1:
  892.     lodsb                ; Get a byte
  893.     or    al,al            ; End of it?
  894.     je    cpys_exit        ; Yep - exit now
  895.     cmp    al,' '            ; Whitespace?
  896.     je    cpys_exit        ; Yep - exit
  897.     cmp    al,9            ; Whitespace?
  898.     je    cpys_exit        ; Yep - exit
  899.     jcxz    cpys_l1            ; If the buffer's full, ignore it
  900.     call    casetize        ; Make it upper case
  901.     stosb                ; Store it
  902.     inc    byte ptr [bx]        ; Count it
  903.     dec    cx            ;
  904.     jmp    short cpys_l1        ; Do the next one
  905. cpys_exit:
  906.     sub    al,al            ; Make sure it's also nul-terminated
  907.     stosb                ;
  908.     dec    si            ; Point 'em back to the stopping points
  909.     dec    di            ;
  910.     restore
  911.     ret                ; Return to caller
  912.  
  913. copy_string    endp
  914.  
  915.  
  916. ;*****************************************************************************
  917. ;
  918. ; Fold a character to upper case.
  919. ;
  920. ; Input:
  921. ;    AL        character to convert
  922. ;
  923. ; Output:
  924. ;    AL        converted character
  925. ;
  926. ; Registers:
  927. ;    All but AL preserved.
  928. ;
  929. ;*****************************************************************************
  930. casetize    proc    near
  931.  
  932.     cmp    al,'a'            ; Is it lower case?
  933.     jb    cstz_exit        ; Nope - exit
  934.     cmp    al,'z'            ; Are you sure?
  935.     ja    cstz_exit        ; Yep - never mind
  936.     xor    al,20h            ; Make it upper case
  937. cstz_exit:
  938.     ret                ; Return to caller
  939.  
  940. casetize    endp
  941.  
  942.  
  943. ;*****************************************************************************
  944. ;
  945. ; Display a message, allowing for expansion of special control characters.
  946. ;
  947. ; Input:
  948. ;    DS:SI        pointer to message to display.
  949. ;
  950. ; Output:
  951. ;    The message is displayed on the console.
  952. ;    The following characters in the message will be treated specially:
  953. ;    ^A (01h)    causes the alias name to be displayed
  954. ;    ^B (02h)    causes the associated path to be displayed
  955. ;    ^C (03h)    causes the alias file name to be displayed
  956. ;
  957. ; Registers:
  958. ;    All preserved.
  959. ;
  960. ;*****************************************************************************
  961. display_message    proc    near
  962.  
  963. assume    ds:todir_data, es:todir_data
  964.  
  965.     save    ax, dx, si
  966. dspm_l1:
  967.     lodsb                ; Get a byte
  968.     or    al,al            ; Is it the end?
  969.     jz    dspm_exit        ; Yep - we're done
  970.     cmp    al,1            ; Need to display the alias?
  971.     jne    dspm_l2            ; Nope - check for the path
  972.     push    si            ; Save where we are
  973.     mov    si,offset alias_name    ; Point to the alias name
  974.     call    display_string        ; Display the alias
  975.     pop    si            ; Get our position back
  976.     jmp    short dspm_l1        ; Loop back
  977. dspm_l2:
  978.     cmp    al,2            ; Need to display the path?
  979.     jne    dspm_l3            ; No - check for alias file name
  980.     push    si            ; Save where we are
  981.     mov    si,offset alias_path    ; Point to the path
  982.     call    display_string        ; Display the path
  983.     pop    si            ; Get our position back
  984.     jmp    short dspm_l1        ; Loop back
  985. dspm_l3:
  986.     cmp    al,3            ; Need to display the alias file path?
  987.     jne    dspm_l4            ; No - display this character
  988.     push    si            ; Save where we are
  989.     mov    si,offset path_file_name; Point to the file name
  990.     call    display_string        ; Display it
  991.     pop    si            ; Get our position back
  992.     jmp    short dspm_l1
  993. dspm_l4:
  994.     mov    dl,al            ; Put it where DOS wants
  995.     mov    ah,6            ; Direct I/O function
  996.     int    21h            ; Display the character
  997.     jmp    short dspm_l1        ; Loop back
  998. dspm_exit:
  999.     restore
  1000.     ret                ; Return to caller
  1001.  
  1002. display_message    endp
  1003.  
  1004.  
  1005. ;*****************************************************************************
  1006. ;
  1007. ; Display a length-prefixed string.
  1008. ;
  1009. ; Input:
  1010. ;    DS:SI        pointer to the string to display
  1011. ;
  1012. ; Output:
  1013. ;    The string is output to stdout.
  1014. ;
  1015. ; Registers:
  1016. ;    All preserved.
  1017. ;
  1018. ;*****************************************************************************
  1019. display_string    proc    near
  1020.  
  1021. assume    ds:todir_data, es:todir_data
  1022.  
  1023.     save    ax, bx, cx, dx, si
  1024.     mov    ah,40h            ; Write the string
  1025.     mov    bx,1            ;  to stdout
  1026.     mov    cl,[si]            ; Get the length byte
  1027.     mov    ch,0            ; Make that a word
  1028.     mov    dx,si            ; Get pointer to buffer
  1029.     inc    dx            ; Skip the length byte
  1030.     int    21h            ; Display the string
  1031.     restore
  1032.     ret                ; Return to caller
  1033.  
  1034. display_string    endp
  1035.  
  1036.  
  1037. program_end    label    byte
  1038.  
  1039.  
  1040. todir_code    ends
  1041.  
  1042.     end    start
  1043.